package com.qianyu.project.config;

import com.alibaba.fastjson.JSON;
import com.qianyu.project.core.context.user.FlowUserManager;
import com.qianyu.project.service.impl.SystemUserServiceImpl;
import com.qianyu.project.utils.ResultTool;
import com.qianyu.project.web.filter.JwtFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * @author gs
 * @date create in 2020/12/23 15:25
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SystemUserServiceImpl systemUserService;
    @Autowired
    private FlowUserManager flowUserManager;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //设置自定义认证
        auth.userDetailsService(systemUserService).passwordEncoder(
                new BCryptPasswordEncoder()
        );
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //所需要用到的静态资源，允许访问
        web.ignoring().antMatchers("/swagger-ui.html",
                "/swagger-ui/*",
                "/swagger-resources/**",
                "/v2/api-docs",
                "/v3/api-docs",
                "/webjars/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭跨域请求伪造
        http.csrf().disable();
        //跨域配置
        http.cors(withDefaults());
        //修改默认的session创建策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //配置表单登陆
        http.formLogin()
                .successForwardUrl("/success")
                .failureForwardUrl("/error")
                .permitAll()
                .and()
                .logout()
                .logoutSuccessUrl("/exit").permitAll();

        //配置其他请求认证
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .exceptionHandling()
                //权限不足处理器
                .accessDeniedHandler((request, response, exception) -> {
                    response.setContentType("application/json; charset=UTF-8");
                    response.getWriter().write(
                            JSON.toJSONString(
                                    ResultTool.failure("权限不足")
                            )
                    );

                })
                //认证失败处理器
                .authenticationEntryPoint((request, response, exception) -> {
                    response.setContentType("application/json; charset=UTF-8");
                    response.getWriter().write(
                            JSON.toJSONString(
                                    ResultTool.failure("请先登陆！")
                            )
                    );
                });

        //添加jwt过滤器
        http.addFilterBefore(new JwtFilter(flowUserManager), BasicAuthenticationFilter.class);
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
